#ifndef HD44780PARALLEL_ANALYZER_H
#define HD44780PARALLEL_ANALYZER_H

#include <Analyzer.h>
#include "HD44780AnalyzerResults.h"
#include "HD44780SimulationDataGenerator.h"

class ProtocolFrameGrabber;

class HD44780AnalyzerSettings;
class ANALYZER_EXPORT HD44780Analyzer : public Analyzer
{
public:
	HD44780Analyzer();
	virtual ~HD44780Analyzer();
	virtual void SetupResults();
	virtual void WorkerThread();
	virtual U32 GenerateSimulationData( U64 newest_sample_requested, U32 sample_rate, SimulationChannelDescriptor** simulation_channels );
	virtual U32 GetMinimumSampleRateHz();
	virtual const char* GetAnalyzerName() const;
	virtual bool NeedsRerun();

    AnalyzerChannelData*    GetClock() { return mClock;}
    void PositionClockAtCapturePoint();
    U64 CalculateDataFromChannels();
    bool IsFramePartOfInitializationSequence( U64 Data );
    void PositionStartMarkerOnChannels();
    bool MoveClockToNextTargetFrameIfPossible();
    void PositionMarkerOnSingleFrameChannels();
    void StoreFrame(  U64 Sample, U64 Data1, U64 Data2, U8 Flag, U8 FrameType );
    bool MoveClockToNextTargetFrame();
    void PositionEndMarkerOnChannels();
    void PositionErrorMarkerOnChannels();

protected: //vars
	std::auto_ptr< HD44780AnalyzerSettings > mSettings;
	std::auto_ptr< HD44780AnalyzerResults >  mResults;
	AnalyzerChannelData*                     mSerial;
	HD44780SimulationDataGenerator           mSimulationDataGenerator;
	bool                                     mSimulationInitilized;
	U32                                      mSampleRateHz;
	U32                                      mStartOfStopBitOffset;
	U32                                      mEndOfStopBitOffset;
    U64                                      mFrameCounter;
    U64                                      mLastFrameCount;
    std::vector< AnalyzerChannelData* >      mData;
	std::vector< U64 >                       mDataMasks;
    std::vector< U32 >                       mChannelPos;
	std::vector< Channel >                   mDataChannels;
	AnalyzerChannelData*                     mClock;
    std::vector<ProtocolFrameGrabber*>       mFrameGenerators;

private:
    /*void Capture7BitFrames();
    void Capture11BitFrames();
    void Capture11BitPartialFrames();
    void Store7BitFrame( U64 Sample, U64 FirstNible, U64 SecondNibble );
    void Store11BitFrame(  U64 Sample, U64 FullByte  );
    inline U64 ConvertDataFrom7BitsTo11Bits( U64 Data );
    inline U64 ConvertDataFrom11BitsPartialTo11Bits( U64 Data );
    inline bool CommandsFromFirstNibbleIsDifferentThanCommandFromSecondNibble( U64 FirstNibble, U64 SecondNibble );
    inline U64 MergeNibblesBetweenTwoConsecutive4BitDataCapturePoints( U64 FirstNibble, U64 SecondNibble );*/


    inline void InitializeThreadArtifacts();
    inline void GetChannelsToSample();
    inline void AdvanceClockToFirstRisingEdge();
    inline void CaptureFrames();

    inline void CreateFrameGrabbers();
    inline void DeleteFrameGrabbers();
    inline void StaticInitializationOfFrameGrabbers();
    inline bool IsFrameWithinInitializationThreashold();
    inline bool IsFrameAnInitializationCommand( U64 Data );
    inline bool IsFrameAFunctionSetCommand( U64 Data );

};

extern "C" ANALYZER_EXPORT const char* __cdecl GetAnalyzerName();
extern "C" ANALYZER_EXPORT Analyzer* __cdecl CreateAnalyzer( );
extern "C" ANALYZER_EXPORT void __cdecl DestroyAnalyzer( Analyzer* analyzer );

#endif //HD44780PARALLEL_ANALYZER_H
